package CelestialDataAccess;

import java.util.Set;

public abstract class SearchCriteria {

    /* Connectives (SQL Server)*/
    public static final String AND = " AND ";
    public static final String OR = " OR ";

    /* Operators (SQL Server) */
    public static final String GT = " > ";
    public static final String GTE = " >= ";
    public static final String LT = " < ";
    public static final String LTE = " <= ";
    public static final String EQU = " = ";
    public static final String NEQ =  "<> ";
    public static final String LIKE = " LIKE ";

    /* The following are initialized by inherited class during instantiation */
    protected String m_strSelectClause;

    protected java.util.HashMap<String, Object> m_mapValues = new java.util.HashMap<String, Object>();
    protected java.util.HashMap<String, String> m_mapOperators = new java.util.HashMap<String, String>();
    
    protected String m_strConnective = SearchCriteria.AND;

    /************************************************************************/
    /* get/set methods */
    public Object getValue(String field){ return m_mapValues.get(field);}
    public Object setValue(String field, Object value){

        /* Blocks clients from adding new fields */
        if(!m_mapValues.containsKey(field)) return null;

        return m_mapValues.put(field, value);
    }
    /*----------------------------------------------------------------------*/
    public String getOperator(String field){ return m_mapOperators.get(field);}
    public String setOperator(String field, String value){

        /* Blocks clients from adding new fields */
        if(!m_mapOperators.containsKey(field)) return null;

        return m_mapOperators.put(field, value);
    }
    /*----------------------------------------------------------------------*/
    public String getConnective(){ return m_strConnective;}
    public void setConnective(String connect){
        if(!connect.equals(AND) && !connect.equals(OR)) return;
        m_strConnective = connect; 
    }
    /*----------------------------------------------------------------------*/
    public boolean hasField(String field){ return m_mapValues.containsKey(field);}
    public Set<String> fieldSet(){ return m_mapValues.keySet();}
    /*----------------------------------------------------------------------*/
    /************************************************************************/
    /* Client methods */
    public String buildSQL(){

        /* Build where clause */
        java.lang.StringBuilder sbWhereClause = new java.lang.StringBuilder("Where ");
        Object objValue;
        String strValue;

        for(String k: this.fieldSet()){
            objValue = this.getValue(k);
            if(objValue==null) continue;

            /* if value is string, enclose quotation */
            if(java.util.regex.Pattern.matches("[0-9]+(\\.[0-9])*", objValue.toString()))
                strValue = objValue.toString();
            else{
                /* if LIKE, enclose with % */
                if(this.getOperator(k).compareTo(SearchCriteria.LIKE)==0)
                    strValue = " '%" + objValue.toString() + "%' ";
                else
                    strValue = "'" + objValue.toString() + "'";
            }
            sbWhereClause.append((k + this.getOperator(k) + strValue + this.getConnective()));
        }
        /* if no criteria, remove where clause;
           else remove the last connective */
        if(sbWhereClause.length() == "Where ".length())
            sbWhereClause.delete(0, 6);
        else
            sbWhereClause.delete(sbWhereClause.length() - this.getConnective().length(), sbWhereClause.length());

        return m_strSelectClause + " " + sbWhereClause.toString();
    }
}
